package com.ruoyi.common.utils.oss;

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.Credentials;
import com.aliyun.oss.common.auth.CredentialsProvider;
import com.aliyun.oss.common.auth.DefaultCredentials;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.ruoyi.common.config.AiBaseInfoConfig;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

@RequiredArgsConstructor
public class OssUtils {

    public static final String ACCESS_KEY_ID = AiBaseInfoConfig.getOssAccessKeyId();
    public static final String ACCESS_KEY_SECRET = AiBaseInfoConfig.getOssAccessKeySecret();
    public static final String END_POINT = AiBaseInfoConfig.getOssEndPoint();
    public static final String BUCKET_NAME = AiBaseInfoConfig.getOssBucketName();
    public static final String OSS_URL = AiBaseInfoConfig.getOssUrl();


    //自定义访问凭证
    public static CredentialsProvider getCredentialsProvider() {

        //自定义访问凭证

        return new CredentialsProvider() {

            // 初始化变量
            String accessKeyId = ACCESS_KEY_ID;
            // 初始化变量
            String accessKeySecrect = ACCESS_KEY_SECRET;
            // 初始化变量
            // String token = null;

            @Override
            public Credentials getCredentials() {
                //TODO
                //自定义访问凭证的获取方法

                // 返回长期凭证 access_key_id, access_key_secrect
                return new DefaultCredentials(accessKeyId, accessKeySecrect);

                // 返回 临时凭证 access_key_id, access_key_secrect, token
                // 对于临时凭证，需要根据过期时间，刷新凭证。
                // return new DefaultCredentials(accessKeyId, accessKeySecrect, token);
            }

            @Override
            public void setCredentials(Credentials credentials) {
            }
        };
    }


    /**
     * 上传文件到阿里云oss
     *
     * @param fileExtension 文件扩展名
     * @param file          文件流
     * @return oss文件地址
     * @throws Exception
     */
    public static String upload(String fileExtension, MultipartFile file) throws Exception {


        String objectName = "llm/" + getCurrentYearMonth() + "/" + System.currentTimeMillis() / 1000 + "." + fileExtension;

        // 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量ossAccessKeyId和ossAccessKeySecret。
        //EnvironmentVariableCredentialsProvider credentialsProvider = new EnvironmentVariableCredentialsProvider().;

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(END_POINT, getCredentialsProvider());

        try {
            InputStream inputStream = file.getInputStream();
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET_NAME, objectName, inputStream);
            // 创建PutObject请求。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

        return OSS_URL + "/" + objectName;

    }

    /**
     * 上传文件到阿里云oss
     *
     * @param fileExtension 文件扩展名
     * @param filePath      文件地址
     * @return oss文件地址
     * @throws Exception
     */
    public static String upload(String fileExtension, String filePath) throws Exception {

        String objectName = "llm/" + getCurrentYearMonth() + "/" + System.currentTimeMillis();
        if (!fileExtension.isEmpty()) {
            objectName += "." + fileExtension;
        } else {
            objectName += ".png";
        }

        // 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量ossAccessKeyId和ossAccessKeySecret。
        //EnvironmentVariableCredentialsProvider credentialsProvider = new EnvironmentVariableCredentialsProvider().;

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(END_POINT, getCredentialsProvider());

        try {
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET_NAME, objectName, getImageInputStream(filePath));
            // 创建PutObject请求。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

        return OSS_URL + "/" + objectName;

    }


    /**
     * 上传文件到阿里云oss
     *
     * @param fileName 文件扩展名
     * @param file     文件流
     * @return oss文件地址
     * @throws Exception
     */
    public static String uploadFileToOss(String fileName, MultipartFile file) throws RuntimeException, IOException {
        String objectName = fileName;
        // 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量ossAccessKeyId和ossAccessKeySecret。
        //EnvironmentVariableCredentialsProvider credentialsProvider = new EnvironmentVariableCredentialsProvider().;
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(END_POINT, getCredentialsProvider());
        try {
            InputStream inputStream = file.getInputStream();
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET_NAME, objectName, inputStream);
            // 创建PutObject请求。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            System.out.println(result);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
            throw new RuntimeException(oe.getErrorMessage());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
            throw new RuntimeException(ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

        return OSS_URL + "/" + objectName;

    }


    /**
     * 从阿里云OSS下载文件
     *
     * @param objectKey
     * @return
     */
    public static File downloadFile(String objectKey) {
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = new OSSClientBuilder().build(END_POINT, getCredentialsProvider());
        try {
            // 下载Object到本地文件，并保存到指定的本地路径中。如果指定的本地文件存在会覆盖，不存在则新建。
            // 如果未指定本地路径，则下载后的文件默认保存到示例程序所属项目对应本地路径中。

            String fileNameWithExtension = objectKey.substring(objectKey.lastIndexOf("/") + 1);
            //识别文件类型
            String fileExtension = "";
            String baseName = "";
            //获取文件后缀
            if (objectKey != null && !objectKey.isEmpty()) {
                int dotIndex = objectKey.lastIndexOf('.');
                if (dotIndex > 0 && dotIndex < objectKey.length() - 1) {
                    // 存在有效后缀
                    // 不带后缀的文件名
                    baseName = objectKey.substring(0, dotIndex);
                    // 后缀，例如 "docx"
                    fileExtension = objectKey.substring(dotIndex);
                } else {
                    // 没有后缀的情况
                    baseName = objectKey;
                    // 无后缀
                    fileExtension = "";
                }
            }
            // 创建临时文件或指定路径文件用于保存下载内容
            // 创建一个临时文件
            File tempFile = File.createTempFile(baseName, fileExtension);
            // 或者指定具体路径：File targetFile = new File("/path/to/save/" + objectKey);

            // 从 OSS 下载到本地文件
            ossClient.getObject(new GetObjectRequest(BUCKET_NAME, fileNameWithExtension), tempFile);

            return tempFile;

        } catch (OSSException oe) {
            oe.printStackTrace();
            throw new RuntimeException("OSS获取文章内容失败：" + oe.getMessage(), oe);
        } catch (ClientException ce) {
            ce.printStackTrace();
            throw new RuntimeException("OSS连接异常：" + ce.getMessage(), ce);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }


    /**
     * 根据图片URL获取图片的输入流
     * 该方法使用RestTemplate来下载指定URL的图片，并以InputStream的形式返回
     *
     * @param imageUrl 图片的URL地址
     * @return 图片的输入流
     * @throws RuntimeException 如果下载图片失败，抛出运行时异常
     */
    public static InputStream getImageInputStream(String imageUrl) {
        // 创建RestTemplate实例，用于发送HTTP请求
        RestTemplate restTemplate = new RestTemplate();

        try {
            // 发送HTTP请求获取图片资源
            ResponseEntity<byte[]> response = restTemplate.getForEntity(new URI(imageUrl), byte[].class);

            // 检查HTTP响应状态码
            if (response.getStatusCode().is2xxSuccessful()) {
                // 如果响应成功，将响应体转换为字节数组并创建ByteArrayInputStream实例返回
                return new ByteArrayInputStream(response.getBody());
            } else {
                // 如果响应失败，抛出包含响应状态码的运行时异常
                throw new RuntimeException("Failed to download image: " + response.getStatusCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
            // 捕获异常，重新抛出包含原始异常的运行时异常
            throw new RuntimeException("Failed to download image", e);
        }
    }


    //获取当前年月 格式yyyy/mm
    public static String getCurrentYearMonth() {
        // 获取当前日期
        LocalDate now = LocalDate.now();

        // 定义日期格式化器
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM");

        // 格式化日期
        String formattedDate = now.format(formatter);

        return formattedDate;
    }

}
